package service

import (
	"fmt"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"

	"kubernate-server/conf"
)

/**
 * Author: 齐全霞
 * Description: Services实现接口
 * Date:2025年9月27日
 */

type ServicesService struct{}

// 请求和响应结构体
type (
	// ServicePortRequest 服务端口请求
	ServicePortRequest struct {
		Name       string             `json:"name"`
		Port       int32              `json:"port"`
		TargetPort intstr.IntOrString `json:"targetPort"`
		NodePort   int32              `json:"nodePort"`
		Protocol   string             `json:"protocol"`
	}

	// ServiceRequest 服务请求
	ServiceRequest struct {
		Labels   map[string]string    `json:"labels"`
		Type     corev1.ServiceType   `json:"type"`
		Selector map[string]string    `json:"selector"`
		Ports    []ServicePortRequest `json:"ports"`
	}

	// ServiceDetailResponse 服务详情响应
	ServiceDetailResponse struct {
		Code                  int                                     `json:"code"`
		Message               string                                  `json:"message"`
		Name                  string                                  `json:"name"`
		Namespace             string                                  `json:"namespace"`
		Status                corev1.ServiceStatus                    `json:"status"`
		Labels                map[string]string                       `json:"labels"`
		Annotations           map[string]string                       `json:"annotations"`
		Selector              map[string]string                       `json:"selector"`
		Type                  corev1.ServiceType                      `json:"type"`
		IP                    string                                  `json:"ip"`
		IPs                   []string                                `json:"ips"`
		Ports                 []corev1.ServicePort                    `json:"ports"`
		SessionAffinity       corev1.ServiceAffinity                  `json:"sessionAffinity"`
		ExternalTrafficPolicy corev1.ServiceExternalTrafficPolicyType `json:"externalTrafficPolicy"`
		Events                []corev1.LoadBalancerIngress            `json:"events"`
		Endpoints             interface{}                             `json:"endpoints"`
	}

	// ServiceListItem 服务列表项
	ServiceListItem struct {
		Namespace  string               `json:"namespace"`
		Name       string               `json:"name"`
		Type       corev1.ServiceType   `json:"type"`
		ClusterIP  string               `json:"clusterIP"`
		ExternalIP []string             `json:"externalIP"`
		Selector   map[string]string    `json:"selector"`
		Ports      []corev1.ServicePort `json:"ports"`
		CreatedAt  string               `json:"createdAt"`
		Labels     map[string]string    `json:"labels"`
	}

	// ServiceListResponse 服务列表响应
	ServiceListResponse struct {
		Code     int               `json:"code"`
		Message  string            `json:"message"`
		Services []ServiceListItem `json:"services"`
	}

	// MultipleDeleteRequest 批量删除请求
	MultipleDeleteRequest struct {
		Services []string `json:"services" binding:"required"`
	}
)

// GetServicesDetail 获取服务详情
func (s *ServicesService) GetServicesDetail(ctx *gin.Context) {
	namespace := ctx.Param("namespace")
	name := ctx.Param("name")

	// 获取服务详情
	service, err := conf.KuberConfigSet.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "获取服务详情失败: " + err.Error(),
		})
		return
	}

	// 获取端点信息
	endpoints, err := s.getEndpoints(ctx, namespace, name)
	var endpointsInterface interface{}
	if err != nil {
		endpointsInterface = gin.H{"message": "获取端点信息失败: " + err.Error()}
	} else {
		endpointsInterface = endpoints
	}

	// 构建响应
	response := ServiceDetailResponse{
		Code:                  20000,
		Message:               "success",
		Name:                  service.Name,
		Namespace:             service.Namespace,
		Status:                service.Status,
		Labels:                service.Labels,
		Annotations:           service.Annotations,
		Selector:              service.Spec.Selector,
		Type:                  service.Spec.Type,
		IP:                    service.Spec.ClusterIP,
		IPs:                   service.Spec.ClusterIPs,
		Ports:                 service.Spec.Ports,
		SessionAffinity:       service.Spec.SessionAffinity,
		ExternalTrafficPolicy: service.Spec.ExternalTrafficPolicy,
		Events:                service.Status.LoadBalancer.Ingress,
		Endpoints:             endpointsInterface,
	}

	ctx.JSON(http.StatusOK, response)
}

// GetServicesList 获取服务列表
func (s *ServicesService) GetServicesList(ctx *gin.Context) {
	namespace := ctx.Param("namespace")

	// 获取查询参数
	nameFilter := ctx.Query("name")

	servicesList, err := conf.KuberConfigSet.CoreV1().Services(namespace).List(ctx, metav1.ListOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "获取服务列表失败: " + err.Error(),
		})
		return
	}

	// 构建服务列表
	services := make([]ServiceListItem, 0, len(servicesList.Items))
	for _, svc := range servicesList.Items {
		// 如果提供了名称过滤，进行匹配
		if nameFilter != "" && !strings.Contains(svc.Name, nameFilter) {
			continue
		}

		services = append(services, ServiceListItem{
			Namespace:  svc.Namespace,
			Name:       svc.Name,
			Labels:     svc.Labels,
			Type:       svc.Spec.Type,
			ClusterIP:  svc.Spec.ClusterIP,
			ExternalIP: svc.Spec.ExternalIPs,
			Selector:   svc.Spec.Selector,
			Ports:      svc.Spec.Ports,
			CreatedAt:  svc.CreationTimestamp.Format("2006-01-02 15:04:05"),
		})
	}

	ctx.JSON(http.StatusOK, ServiceListResponse{
		Code:     20000,
		Message:  "success",
		Services: services,
	})
}

// CreateService 创建服务
func (s *ServicesService) CreateService(ctx *gin.Context) {
	namespace := ctx.Param("namespace")
	name := ctx.Param("name")

	service, err := s.parseServiceRequest(ctx, name, namespace)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40000,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	_, err = conf.KuberConfigSet.CoreV1().Services(namespace).Create(ctx, service, metav1.CreateOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "创建服务失败: " + err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
	})
}

// UpdateService 更新服务
func (s *ServicesService) UpdateService(ctx *gin.Context) {
	namespace := ctx.Param("namespace")
	name := ctx.Param("name")

	// 获取现有服务
	existingService, err := conf.KuberConfigSet.CoreV1().Services(namespace).Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40400,
			"message": "服务不存在: " + err.Error(),
		})
		return
	}

	// 解析更新请求
	var request ServiceRequest
	if err := ctx.BindJSON(&request); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40000,
			"message": "请求参数错误: " + err.Error(),
		})
		return
	}

	// 更新服务配置
	updatedService := existingService.DeepCopy()
	if request.Labels != nil {
		updatedService.Labels = request.Labels
	}
	if request.Selector != nil {
		updatedService.Spec.Selector = request.Selector
	}
	if request.Ports != nil {
		updatedService.Spec.Ports = s.convertToServicePorts(request.Ports)
	}

	_, err = conf.KuberConfigSet.CoreV1().Services(namespace).Update(ctx, updatedService, metav1.UpdateOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "更新服务失败: " + err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
	})
}

// DeleteService 删除服务
func (s *ServicesService) DeleteService(ctx *gin.Context) {
	namespace := ctx.Param("namespace")
	name := ctx.Param("name")
	err := conf.KuberConfigSet.CoreV1().Services(namespace).Delete(ctx, name, metav1.DeleteOptions{})
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "删除服务失败: " + err.Error(),
		})
		return
	}

	ctx.JSON(http.StatusOK, gin.H{
		"code":    20000,
		"message": "success",
	})
}

// DeleteMultipleServices 删除多个Service
func (s *ServicesService) DeleteMultipleServices(ctx *gin.Context) {
	namespace := ctx.Param("namespace")

	var request MultipleDeleteRequest
	if err := ctx.BindJSON(&request); err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "error:" + err.Error(),
		})
		return
	}

	if len(request.Services) == 0 {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40000,
			"message": "error: services can't be empty",
		})
		return
	}

	// 用于记录成功和失败的服务名
	success := make([]string, 0)
	failures := make([]string, 0)

	for _, serviceName := range request.Services {
		err := conf.KuberConfigSet.CoreV1().Services(namespace).Delete(ctx, serviceName, metav1.DeleteOptions{})
		if err != nil {
			failures = append(failures, serviceName)
		} else {
			success = append(success, serviceName)
		}
	}

	// 根据是否有失败情况返回不同的消息
	if len(failures) == 0 {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    20000,
			"message": "所有服务删除成功",
			"data": gin.H{
				"success": success,
			},
		})
	} else {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "部分服务删除失败",
			"data": gin.H{
				"success": success,
				"failed":  failures,
			},
		})
	}
}

// DeleteServiceByLabel 根据标签删除Service
func (s *ServicesService) DeleteServiceByLabel(ctx *gin.Context) {
	namespace := ctx.Param("namespace")
	labelSelector := ctx.Query("labelSelector")
	fmt.Println(labelSelector)
	if labelSelector == "" {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40000,
			"message": "error: labelSelector can't be empty",
		})
		return
	}

	listOptions := metav1.ListOptions{
		LabelSelector: labelSelector,
	}
	fmt.Println(listOptions)
	services, err := conf.KuberConfigSet.CoreV1().Services(namespace).List(ctx, listOptions)
	fmt.Println(services)
	if err != nil {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "error:" + err.Error(),
		})
		return
	}
	if len(services.Items) == 0 {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    40400,
			"message": "error: No found match labelSelector selector's service",
		})
		return
	}
	// 批量删除匹配的服务
	// 用于记录成功和失败的服务名
	success := make([]string, 0)
	failures := make([]string, 0)

	// 批量删除匹配的服务
	for _, service := range services.Items {
		err := conf.KuberConfigSet.CoreV1().Services(namespace).Delete(ctx, service.Name, metav1.DeleteOptions{})
		if err != nil {
			failures = append(failures, service.Name)
		} else {
			success = append(success, service.Name)
		}
	}

	// 根据是否有失败情况返回不同的消息
	if len(failures) == 0 {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    20000,
			"message": "所有服务删除成功",
			"data": gin.H{
				"success": success,
			},
		})
	} else {
		ctx.JSON(http.StatusOK, gin.H{
			"code":    50000,
			"message": "部分服务删除失败",
			"data": gin.H{
				"success": success,
				"failed":  failures,
			},
		})
	}
}

// 辅助方法

// getEndpoints 获取端点信息
func (s *ServicesService) getEndpoints(ctx *gin.Context, namespace, name string) (interface{}, error) {
	endpoints, err := conf.KuberConfigSet.CoreV1().Endpoints(namespace).Get(ctx, name, metav1.GetOptions{})
	if err != nil {
		return gin.H{"message": "获取端点信息失败: " + err.Error()}, err
	}

	return gin.H{
		"namespace": namespace,
		"name":      name,
		"subsets":   endpoints.Subsets,
	}, nil
}

// parseServiceRequest 解析服务请求
func (s *ServicesService) parseServiceRequest(ctx *gin.Context, name, namespace string) (*corev1.Service, error) {
	var request ServiceRequest

	// 设置默认值
	request.Type = corev1.ServiceTypeClusterIP
	request.Selector = map[string]string{"app": name}
	request.Ports = []ServicePortRequest{
		{
			Name:       "http",
			Port:       80,
			TargetPort: intstr.FromInt(8080),
			Protocol:   "TCP",
		},
	}

	// 尝试绑定JSON，如果失败则使用默认值
	if err := ctx.BindJSON(&request); err != nil {
		// 这里可以选择记录日志，但继续使用默认值
	}

	return &corev1.Service{
		ObjectMeta: metav1.ObjectMeta{
			Name:      name,
			Namespace: namespace,
			Labels:    request.Labels,
		},
		Spec: corev1.ServiceSpec{
			Type:     request.Type,
			Selector: request.Selector,
			Ports:    s.convertToServicePorts(request.Ports),
		},
	}, nil
}

// convertToServicePorts 转换端口配置
func (s *ServicesService) convertToServicePorts(portRequests []ServicePortRequest) []corev1.ServicePort {
	servicePorts := make([]corev1.ServicePort, len(portRequests))

	for i, port := range portRequests {
		protocol := corev1.ProtocolTCP
		if port.Protocol == "UDP" {
			protocol = corev1.ProtocolUDP
		}

		servicePorts[i] = corev1.ServicePort{
			Name:       port.Name,
			Port:       port.Port,
			TargetPort: port.TargetPort,
			NodePort:   port.NodePort,
			Protocol:   protocol,
		}
	}

	return servicePorts
}
